package cn.bigfire.wzdj.util.tool;

import cn.bigfire.wzdj.util.ByteUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@Slf4j
public class FileDropTargetListener extends DropTargetAdapter {
    @Override
    @SneakyThrows
    public void drop(DropTargetDropEvent dtde) {
        try {
            dtde.acceptDrop(DnDConstants.ACTION_COPY);
            Transferable transferable = dtde.getTransferable();
            if (!transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                return;
            }
            @SuppressWarnings("unchecked")
            List<File> fileList = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
            if (fileList.isEmpty()) {
                return;
            }
            File file = fileList.get(0);
            String absolutePath = file.getAbsolutePath();
            String type = FileTypeUtil.getType(file);
            if ("saz".equals(type) || "zip".equals(type)) {
                ZipFile zipFile = new ZipFile(file);

                Enumeration<? extends ZipEntry> entries = zipFile.entries();
                while (entries.hasMoreElements()) {
                    ZipEntry entry = entries.nextElement();
                    if (entry.getName().startsWith("raw/") && entry.getName().endsWith("_w.txt")) {
                        log.info(entry.getName());
                        String log = handlerFile(ZipUtil.getStream(zipFile, entry));
                        String logName = absolutePath + "_" +  entry.getName().replace("raw/", "").replace(".txt", ".log");
                        FileUtil.writeString(log, logName, "UTF-8");
                    }
                }
            } else if ("txt".equals(type)) {
                String log = handlerFile(Files.newInputStream(file.toPath()));
                String logName = absolutePath.replace(".txt", ".log");
                FileUtil.writeString(log, logName, "UTF-8");
            } else {
                log.error("不认识的文件类型" + type);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            dtde.dropComplete(true);
        }
    }


    @SneakyThrows
    public static String handlerFile(InputStream  is)  {
        try {
            BufferedInputStream bis = new BufferedInputStream(is);//增加缓存，防止zip  InputSteam 8192字节限制
            PushbackInputStream pis = new PushbackInputStream(bis);
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = readLine(pis)) != null) {
                if (line.startsWith("Request-Length:") || line.startsWith("Response-Length:")) {
                    boolean isRequest = line.startsWith("Request-Length:");
                    int id = Integer.parseInt(StrUtil.subAfter(readLine(pis), ":", false).trim());
//                    int bitFlags = Integer.parseInt(StrUtil.subAfter(readLine(pis), ":", false).trim());
//                    String doneReadStr = StrUtil.subAfter(readLine(pis), ":", false);
//                    String beginSendStr = StrUtil.subAfter(readLine(pis), ":", false);
                    readLine(pis);readLine(pis);readLine(pis);
                    String doneSendStr = StrUtil.subBetween(readLine(pis), ":", ".");
                    String splitLine = readLine(pis);
                    //跳过5行
//                    for (int i = 0; i < 5; i++) {
//                        readLine(pis);
//                    }
                    //debug错误数据id
//                    if (id != 54) {
//                        continue;
//                    }

                    WSFrame wsFrame = WSFrame.ofInputStream(pis,id,isRequest);
                    if (wsFrame == null) {
                        continue;
                    }
                    wsFrame.setRequest(isRequest);

                    //fiddler抓包数据  模拟fiddler展示
                    byte[] payloadBytes = wsFrame.getPayloadBytes();
                    //20Hex
//                    String dataHex = HexUtil.encodeHexStr(payloadBytes);
//                    String hex = StrUtil.subWithLength(dataHex, 0, 20);//hex展示长度
                    //20Hex  虽然20字节，实际数据可能小于20字节
                    byte[] bytes = ByteUtil.subBefore(payloadBytes, 76);
                    String hex = HexUtil.encodeHexStr(bytes);

                    String direction = isRequest ? "↑" : "↓";
                    String format = String.format("%s%s[%s](%s)%s,%s%n",
                            direction, id, wsFrame.getType(), wsFrame.getRealLen(), hex, doneSendStr);
                    System.out.printf(format);
                    sb.append(format);
                    if (WSFrame.OPCODE_TEXT == wsFrame.getOpCode() || WSFrame.OPCODE_BINARY == wsFrame.getOpCode()) {//binbary
                        ProtocolHandler.onMessage(wsFrame,id,isRequest, sb);
                    }
                }
            }
            return sb.toString();
        } catch (Exception e) {
           e.printStackTrace();
            return e.getMessage();
        }
    }

    // 常量定义换行符
    private static final byte LF = 0x0A; // '\n'
    private static final byte CR = 0x0D; // '\r'

    /**
     * 从输入流中读取一行，返回字符串。
     *
     * @param pis 输入流
     * @return 读取到的一行，如果没有更多数据则返回null
     * @throws IOException 如果发生I/O错误
     */
    public static String readLine(PushbackInputStream pis) throws IOException {
        StringBuilder lineBuilder = new StringBuilder();
        int b;
        while ((b = pis.read()) != -1) {
            if (b == CR) {
                // 处理 '\r\n' 和 '\r'
                int next = pis.read();
                if (next == -1) {
                    // 如果 '\r' 是最后一字节，则直接返回 '\r'
                    lineBuilder.append((char) CR);
                    break;
                } else if (next != LF) {
                    // 如果 '\r' 后不是 '\n'，则将 '\r' 放回输入流并返回
                    pis.unread(next);
                    lineBuilder.append((char) CR);
                }
                // 无论是 '\r\n' 还是单独的 '\r'，都表示换行
                break;
            } else if (b == LF) {
                // 处理单独的 '\n'
                break;
            } else {
                // 将读取到的字符添加到构建器中
                lineBuilder.append((char) b);
            }
        }
        // 如果没有读取到任何字符且输入流已经结束，则返回null
        if (lineBuilder.length() == 0 && b == -1) {
            return null;
        }
        return lineBuilder.toString();
    }

}
